using System;
using ActiproSoftware.SyntaxEditor;
using ActiproSoftware.SyntaxEditor.Addons.Dynamic;

namespace RWXMLEdit.Client 
{
	/// <summary>
	/// Provides an implementation of a <c>HTML</c> syntax language that can perform automatic outlining.
	/// </summary>
	public class HtmlDynamicSyntaxLanguage : XmlDynamicSyntaxLanguage {
		
		/////////////////////////////////////////////////////////////////////////////////////////////////////
		// OBJECT
		/////////////////////////////////////////////////////////////////////////////////////////////////////
		
		/// <summary>
		/// This constructor is for designer use only and should never be called by your code.
		/// </summary>
		public HtmlDynamicSyntaxLanguage() : base() {}

		/// <summary>
		/// Initializes a new instance of the <c>HtmlDynamicSyntaxLanguage</c> class. 
		/// </summary>
		/// <param name="key">The key of the language.</param>
		/// <param name="secure">Whether the language is secure.</param>
		public HtmlDynamicSyntaxLanguage(string key, bool secure) : base(key, secure) {}

		/////////////////////////////////////////////////////////////////////////////////////////////////////
		// PUBLIC PROCEDURES
		/////////////////////////////////////////////////////////////////////////////////////////////////////
		
		/// <summary>
		/// Returns token parsing information for automatic outlining that determines if the current <see cref="IToken"/>
		/// in the <see cref="TokenStream"/> starts or ends an outlining node.
		/// </summary>
		/// <param name="tokenStream">A <see cref="TokenStream"/> that is positioned at the <see cref="IToken"/> requiring outlining data.</param>
		/// <param name="outliningKey">Returns the outlining node key to assign.  A <see langword="null"/> should be returned if the token doesn't start or end a node.</param>
		/// <param name="tokenAction">Returns the <see cref="OutliningNodeAction"/> to take for the token.</param>
		public override void GetTokenOutliningAction(TokenStream tokenStream, ref string outliningKey, ref OutliningNodeAction tokenAction) {
			// Get the token
			IToken token = tokenStream.Peek();
			string languageTokenKey = token.Language.Key + "_" + token.Key;

			// See if the token starts or ends an outlining node
			switch (languageTokenKey) {
				case "CSS_PropertyStartToken":
					outliningKey = "CSS_PropertyBlock";
					tokenAction = OutliningNodeAction.Start;
					break;
				case "CSS_PropertyEndToken":
					outliningKey = "CSS_PropertyBlock";
					tokenAction = OutliningNodeAction.End;
					break;
				case "CSS_CommentStartToken":
					outliningKey = "CSS_Comment";
					tokenAction = OutliningNodeAction.Start;
					break;
				case "CSS_CommentEndToken":
					outliningKey = "CSS_Comment";
					tokenAction = OutliningNodeAction.End;
					break;
				case "JScript_OpenCurlyBraceToken":
					outliningKey = "JScript_CodeBlock";
					tokenAction = OutliningNodeAction.Start;
					break;
				case "JScript_CloseCurlyBraceToken":
					outliningKey = "JScript_CodeBlock";
					tokenAction = OutliningNodeAction.End;
					break;
				case "JScript_MultiLineCommentStartToken":
					outliningKey = "JScript_MultiLineComment";
					tokenAction = OutliningNodeAction.Start;
					break;
				case "JScript_MultiLineCommentEndToken":
					outliningKey = "JScript_MultiLineComment";
					tokenAction = OutliningNodeAction.End;
					break;
				default:
					// If a language change is occurring (tokenAction is only initialized to Start or End on language transitions)...
					if (tokenAction != OutliningNodeAction.NoChange) {
						if (token.HasFlag(LexicalParseFlags.LanguageStart)) {
							if (tokenStream.Position > 0) {
								IToken previousToken = tokenStream.ReadReverse();
								if (previousToken.LexicalState.Key == "ASPDirectiveResponseWriteState") {
									// Don't do outlining on <%=  %> blocks
									outliningKey = null;
									tokenAction = OutliningNodeAction.NoChange;
								}
							}
						}
						else if (token.HasFlag(LexicalParseFlags.LanguageEnd)) {
							tokenStream.Read();
							if (!tokenStream.IsDocumentEnd) {
								IToken nextToken = tokenStream.Peek();
								if (nextToken.LexicalState.Key == "ASPDirectiveResponseWriteState") {
									// Don't do outlining on <%=  %> blocks
									outliningKey = null;
									tokenAction = OutliningNodeAction.NoChange;
								}
							}
						}
					}
					break;
			}
		}
		
		/// <summary>
		/// Occurs after a <see cref="Trigger"/> is activated
		/// for a <see cref="SyntaxEditor"/> that has a <see cref="Document"/> using this language.
		/// </summary>
		/// <param name="syntaxEditor">The <see cref="SyntaxEditor"/> that will raise the event.</param>
		/// <param name="e">An <c>TriggerEventArgs</c> that contains the event data.</param>
		protected override void OnSyntaxEditorTriggerActivated(SyntaxEditor syntaxEditor, TriggerEventArgs e) {
			switch (e.Trigger.Key) {
				case "TagAutoCompleteTrigger": {
					// Call the base method
					base.OnSyntaxEditorTriggerActivated(syntaxEditor, e);
					break;
				}
				case "TagListTrigger": {
					// Get the member list
					IntelliPromptMemberList memberList = syntaxEditor.IntelliPrompt.MemberList;
					memberList.ResetAllowedCharacters();
					memberList.AllowedCharacters.Add('!');
					memberList.AllowedCharacters.Add('-');

					// Set IntelliPrompt ImageList
					memberList.ImageList = SyntaxEditor.ReflectionImageList;

					// Add items to the list
					int imageIndex = (int)ActiproSoftware.Products.SyntaxEditor.IconResource.XmlTag;
					memberList.Clear();
					memberList.Add(new IntelliPromptMemberListItem("<!-- -->", (int)ActiproSoftware.Products.SyntaxEditor.IconResource.XmlComment, null, "!-- ", " -->"));
					memberList.Add(new IntelliPromptMemberListItem("a", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("acronym", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("address", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("applet", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("area", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("b", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("base", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("basefont", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("bdo", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("bgsound", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("big", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("blockquote", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("body", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("br", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("button", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("caption", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("center", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("cite", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("code", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("col", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("colgroup", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("dd", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("del", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("dfn", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("dir", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("div", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("dl", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("dt", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("em", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("embed", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("fieldset", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("form", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("frame", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("frameset", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("h1", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("h2", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("h3", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("h4", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("h5", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("h6", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("head", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("hr", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("html", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("i", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("iframe", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("img", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("input", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("ins", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("isindex", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("kbd", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("label", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("legend", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("li", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("link", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("listing", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("map", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("marquee", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("menu", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("meta", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("nobr", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("noframes", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("noscript", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("object", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("ol", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("option", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("p", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("param", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("plaintext", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("pre", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("q", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("s", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("samp", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("script", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("select", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("small", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("span", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("strike", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("strong", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("style", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("sub", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("sup", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("table", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("tbody", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("td", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("textarea", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("tfoot", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("th", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("thead", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("title", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("tr", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("tt", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("u", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("ul", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("var", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("xml", imageIndex));
					memberList.Add(new IntelliPromptMemberListItem("xmp", imageIndex));

					// Show the list
					if (memberList.Count > 0)
						memberList.Show();
					break;
				}
			}
		}

		/// <summary>
		/// Allows for setting the collapsed text for the specified <see cref="OutliningNode"/>.
		/// </summary>
		/// <param name="node">The <see cref="OutliningNode"/> that is requesting collapsed text.</param>
		public override void SetOutliningNodeCollapsedText(OutliningNode node) {
			if (node.ParseData != null) {
				switch (node.ParseData.Key) {
					case "CSS_Comment":
						node.CollapsedText = "/**/";
						break;
					case "CSS_PropertyBlock":
						node.CollapsedText = "{...}";
						break;
					case "JScript_MultiLineComment":
						node.CollapsedText = "/**/";
						break;
				}
			}
		}

	}
}
